from abc import ABC, abstractmethod
from datetime import datetime
from typing import Dict, List, Any
import os

class BaseReporter(ABC):
    """报告生成器基类，定义报告生成的基本接口"""
    
    def __init__(self, output_dir: str):
        self.output_dir = output_dir
        self.timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
        self._create_output_directories()
    
    def _create_output_directories(self) -> None:
        """创建输出目录"""
        try:
            os.makedirs(self.output_dir, exist_ok=True)
            self.scan_dir = os.path.join(self.output_dir, self.timestamp)
            os.makedirs(self.scan_dir, exist_ok=True)
        except OSError as e:
            raise ReporterError(f"创建输出目录失败: {str(e)}")
    
    @abstractmethod
    def generate(self, results: List[Dict[str, Any]], scan_info: Dict[str, Any]) -> None:
        """生成报告的抽象方法"""
        pass
    
    def validate_data(self, results: List[Dict[str, Any]], scan_info: Dict[str, Any]) -> bool:
        """验证输入数据的有效性"""
        if not isinstance(results, list):
            raise ReporterError("扫描结果必须是列表类型")
        
        if not isinstance(scan_info, dict):
            raise ReporterError("扫描信息必须是字典类型")
        
        required_scan_info = {'start_time', 'end_time', 'total_hosts', 'total_ports'}
        missing_fields = required_scan_info - set(scan_info.keys())
        if missing_fields:
            raise ReporterError(f"扫描信息缺少必要字段: {', '.join(missing_fields)}")
        
        for result in results:
            required_fields = {'target', 'port', 'status', 'service', 'latency', 'service_info'}
            if not all(field in result for field in required_fields):
                raise ReporterError(f"扫描结果缺少必要字段: {required_fields - set(result.keys())}")
        
        return True

class ReporterError(Exception):
    """报告生成器异常类"""
    pass 